home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / AppleShare API / Extras / ServerEventHandler.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-01-03  |  12.2 KB  |  393 lines  |  [TEXT/MPS ]

  1. /*
  2. **    Server Event Handler
  3. **    The server event handler usnit found in the AppleShare 3.0 Developer's
  4. **    Kit Server Control and Server Event Handling document.
  5. **
  6. **    by J. Luther, Apple Developer Technical Support
  7. **    Copyright Apple Computer, Inc. 1992-1994
  8. **    All rights reserved
  9. **
  10. **    Port from Pascal to C - 9/8/1994 JML
  11. **
  12. **    This file contains the server event handler, the server event record
  13. **    processor, and related routines.
  14. */
  15.  
  16. /*****************************************************************************/
  17.  
  18. #include <AppleTalk.h>
  19. #include <Processes.h>
  20. #include <Errors.h>
  21. #include <Memory.h>
  22. #include <Packages.h>
  23. #include "ServerControlIntf.h"
  24. #include "ServerEventIntf.h"
  25.  
  26. /*****************************************************************************/
  27.  
  28. /*
  29. **    This value indicates how many server events can be queued for
  30. **    ProcessServerEvents to handle later. If you expect a large number of
  31. **    server events to come in over a shart amount of time, increase this
  32. **    number.
  33. */
  34.  
  35. enum
  36. {
  37.     kNumberServerEvents = 100
  38. };
  39.  
  40. /*****************************************************************************/
  41.  
  42. /*
  43. **    Add required queue element fields to a server event record so we can
  44. **    use it as an OS queue element.
  45. */
  46.  
  47. struct    SERecQElem
  48. {
  49.     QElemPtr            qLink;
  50.     short                qType;
  51.     ServerEventRecord    theSERec;
  52. };
  53. typedef struct SERecQElem SERecQElem;
  54. typedef SERecQElem *SERecQElemPtr;
  55.  
  56. /*
  57. **    Extend the tSEQEntry with a few items we need access to within the
  58. **    server event handler.
  59. */
  60.  
  61. struct    ExtendedSEQEntry
  62. {
  63.     tSEQEntry            theSEQEntry;    /* a server event queue entry */
  64.     QHdr                freeQ, usedQ;    /* queue headers for server */
  65.                                         /* event record queues */
  66.     SERecQElemPtr        seRecArrayPtr;    /* pointer to allocated array */
  67.                                         /* of SERecQElem */
  68.     ProcessSerialNumber    ourPSN;            /* the application's PSN */
  69. };
  70. typedef struct ExtendedSEQEntry ExtendedSEQEntry;
  71. typedef ExtendedSEQEntry *ExtendedSEQEntryPtr;
  72.  
  73. /*****************************************************************************/
  74.  
  75. /*
  76. **    The global extended tSEQEntry record
  77. */
  78.  
  79. ExtendedSEQEntry    gExtendedSEQEntry;
  80.  
  81. /*****************************************************************************/
  82.  
  83. OSErr    InstallServerEventHandler(void);
  84.  
  85. OSErr    RemoveServerEventHandler(void);
  86.  
  87. void    ProcessServerEvents(void);
  88.  
  89. /*****************************************************************************/
  90.  
  91. /*
  92. **    This function calls SCInstallServerEventProc to install
  93. **    a server event handler.    
  94. */
  95.  
  96. static    OSErr    MySCInstallServerEventProc(const tSEQEntry * const theSEHandler)
  97. {
  98.     SCParamBlockRec    scPB;
  99.     
  100.     scPB.serverEventPB.scSEQEntryPtr = (Ptr)theSEHandler;
  101.     scPB.serverEventPB.scCode = SCInstallServerEventProc;
  102.     
  103.     return ( SyncServerDispatch(&scPB) );
  104. }
  105.  
  106. /*****************************************************************************/
  107.  
  108. /*
  109. **    This function calls SCRemoveServerEventProc to remove a
  110. **    server event handler.
  111. */
  112.  
  113. static    OSErr    MySCRemoveServerEventProc(const tSEQEntry * const theSEHandler)
  114. {
  115.     SCParamBlockRec    scPB;
  116.     
  117.     scPB.serverEventPB.scSEQEntryPtr = (Ptr)theSEHandler;
  118.     scPB.serverEventPB.scCode = SCRemoveServerEventProc;
  119.     
  120.     return ( SyncServerDispatch(&scPB) );
  121. }
  122.  
  123. /*****************************************************************************/
  124.  
  125. /*
  126. **    TheSrvrEventHandler shows what should be done in a server event handler
  127. **    and no more: It gets a server event record from the free queue of
  128. **    application supplied server event records; it copies
  129. **    AppleShare's server event record (pointed to by theSERecPtr) into the
  130. **    application's server event record; it puts the application's server
  131. **    event record into the used queue where it can be serviced from the
  132. **    application's event loop; and then, it calls WakeUpProcess so the event
  133. **    loop can handle the server event record in the queue as soon as possible.
  134. **
  135. **    Note: This code handles the out of free server event record condition
  136. **    by getting the oldest server event record from the usedQ. Depending on
  137. **    your purposes for recording server events, you may want to do something
  138. **    different. For example, you may just want to set a flag to tell the
  139. **    ProcessServerEvents function to allocate more server event records (since
  140. **    you can't do that here).
  141. */
  142.  
  143. static    pascal    void    TheSrvrEventHandler(ExtendedSEQEntry * const theSEQPtr,
  144.                                             const ServerEventRecord * const theSERecPtr)
  145. {
  146.     SERecQElemPtr    theSERecQElemPtr;
  147.     
  148.     if ( theSEQPtr->freeQ.qHead != NULL )
  149.     {
  150.         /* Get the server event record out of the freeQ */
  151.         theSERecQElemPtr = (SERecQElemPtr)theSEQPtr->freeQ.qHead;
  152.         /* Do nothing with errors. You'd better not be getting them! */
  153.         (void) Dequeue((QElemPtr)theSERecQElemPtr, &(theSEQPtr->freeQ));
  154.     }
  155.     else
  156.     {
  157.         /* The freeQ is empty, so get the oldest server */
  158.         /* event record out of the usedQ */
  159.         theSERecQElemPtr = (SERecQElemPtr)theSEQPtr->usedQ.qHead;
  160.         /* Do nothing with errors. You'd better not be getting them! */
  161.         (void) Dequeue((QElemPtr)theSERecQElemPtr, &(theSEQPtr->usedQ));
  162.     }
  163.  
  164.     /* Copy the server event record into my server event record */
  165.     theSERecQElemPtr->theSERec = *theSERecPtr;
  166.  
  167.     /* And enqueue my server event record into the usedQ */
  168.     Enqueue((QElemPtr)theSERecQElemPtr, &(theSEQPtr->usedQ));
  169.  
  170.     /* Wake up our process so it can handle the server event record ASAP */
  171.     /* Do nothing with errors. You'd better not be getting them! */
  172.     (void) WakeUpProcess(&(theSEQPtr->ourPSN));
  173. }
  174.  
  175. /*****************************************************************************/
  176.  
  177. /*
  178. **    InitSEQEntry initializes the fields of gExtendedSEQEntry to zero,
  179. **    allocates kNumberServerEvents of SERecQElem and enqueues them into the
  180. **    free queue of gExtendedSEQEntry, and gets the applications process
  181. **    serial number and puts it in gExtendedSEQEntry so the server event
  182. **    handler can wake up the process.  InitSEQEntry returns true if the array
  183. **    of SERecQElem was allocated.
  184. */
  185.  
  186. static    Boolean    InitSEQEntry(void)
  187. {
  188.     SERecQElemPtr    theQElemsPtr;
  189.     short            index;
  190.     Boolean            result = false;
  191.     
  192.     /* Point to server event handler */
  193.     gExtendedSEQEntry.theSEQEntry.SEQentry.CallAddr =
  194.         (ATalkTransitionEventUPP)TheSrvrEventHandler;
  195.  
  196.     /* Initially clear all SEeventFlags */
  197.     gExtendedSEQEntry.theSEQEntry.SEeventFlag = 0;
  198.  
  199.     /* and clear all SEwhichAFPFlags */
  200.     gExtendedSEQEntry.theSEQEntry.SEwhichAFPFlag[0] = 0;
  201.     gExtendedSEQEntry.theSEQEntry.SEwhichAFPFlag[1] = 0;
  202.  
  203.     /* And clear all SEwhichSCFlags */
  204.     gExtendedSEQEntry.theSEQEntry.SEwhichSCFlag = 0;
  205.  
  206.     /* Allocate some memory for the server event */
  207.     /* records and initialize the buffer queues. */
  208.     gExtendedSEQEntry.seRecArrayPtr =
  209.         (SERecQElemPtr)NewPtr(kNumberServerEvents * (long)sizeof(SERecQElem));
  210.     if ( gExtendedSEQEntry.seRecArrayPtr != NULL )
  211.     {
  212.         /* Initialize the usedQ header */
  213.         gExtendedSEQEntry.usedQ.qFlags = 0;
  214.         gExtendedSEQEntry.usedQ.qHead = NULL;
  215.         gExtendedSEQEntry.usedQ.qTail = NULL;
  216.  
  217.         /* Initialize the freeQ header */
  218.         gExtendedSEQEntry.freeQ.qFlags = 0;
  219.         gExtendedSEQEntry.freeQ.qHead = NULL;
  220.         gExtendedSEQEntry.freeQ.qTail = NULL;
  221.  
  222.         /* The free queue holds all of our server */
  223.         /* event records initially, so add the */
  224.         /* SERecQElems to the freeQ */
  225.         theQElemsPtr = gExtendedSEQEntry.seRecArrayPtr;
  226.         for ( index = 1; index <= kNumberServerEvents; ++index )
  227.         {
  228.             Enqueue((QElemPtr)theQElemsPtr, &(gExtendedSEQEntry.freeQ));
  229.             ++theQElemsPtr;
  230.         }
  231.  
  232.         result = true;    /* everything is OK */
  233.     }
  234.  
  235.     /* Get our process serial number */
  236.     (void) GetCurrentProcess(&(gExtendedSEQEntry.ourPSN));
  237.     
  238.     return ( result );
  239. }
  240.  
  241. /*****************************************************************************/
  242.  
  243. /*
  244. **    SetSEFlags sets the server event flags of gExtendedSEQEntry to tell
  245. **    AppleShare's server event mechanism which server events your
  246. **    application's server event handler are interested in. You can set the
  247. **    SE flags either before or after your server event handler is installed.
  248. **    IMPORTANT NOTES:
  249. **    •    Your server event handler will be called based on the current
  250. **        settings of SEeventFlag. Make sure SEeventFlag is either initialized
  251. **        to zero (meaning your server event handler is not interested in any
  252. **        server events) or initialized for the specific server events your
  253. **        application is interested in before you install your server event
  254. **        handler.                        }
  255. **    •    If you set the bCSEHAFPInDoRequest or bCSEHAFPInSendResponse bits
  256. **        in SEeventFlag after your server event handler is installed, make
  257. **        sure you initialize the SEwhichAFPFlag bits first.
  258. **    •    If you set the bCSEHServerControlCall bit in SEeventFlag after your
  259. **        server event handler is installed, make sure you initialize the
  260. **        SEwhichSCFlag bits first.
  261. */
  262.  
  263. static    void    SetSEFlags(void)
  264. {
  265.     /*
  266.     **    If the bCSEHAFPInDoRequest or bCSEHAFPInSendResponse bits in
  267.     **    SEeventFlag are going to be set, then indicate what AFP calls
  268.     **    you're interested in. For example:
  269.     **        gExtendedSEQEntry.theSEQEntry.SEwhichAFPFlag[1] &= (1L << afpOpenFork);
  270.     **    will cause a server event for the afpOpenFork AFP call.
  271.     */
  272.     
  273.     /*    • add your code here • */
  274.         
  275.     /*
  276.     **    If the bCSEHServerControlCall bit in SEeventFlag is going to be set,
  277.     **    then indicate what server control calls you're interested in.
  278.     **    For example:
  279.     **        gExtendedSEQEntry.theSEQEntry.SEwhichSCFlag &= (1L << SCSetSetupInfo);
  280.     **    will cause a server event for the SCSetSetupInfo server control call.
  281.     */
  282.     
  283.     /*    • add your code here • */
  284.  
  285.     /*
  286.     **    Indicate what server events you'd like to be notified of by setting
  287.     **    bits in the SEeventFlag longword.  For example:
  288.     **        gExtendedSEQEntry.SEeventFlag &= (1L << bCSEHVolumePrep);
  289.     **    will cause a server event every time the server prepares a volume
  290.     **    for use with AppleShare.
  291.     */
  292.     
  293.     /*    • add your code here • */
  294. }
  295.  
  296. /*****************************************************************************/
  297.  
  298. /*
  299. **    ProcessServerEvents should be called every time through the event loop
  300. **    to see if there are any server event records to process. If there aren't
  301. **    any, then it exits immediately. If there are any, then it processes the
  302. **    server event records in the used queue until none are left.
  303. **    This kind of assumes that processing server events doesn't take very long.
  304. **    If processing them is a time consuming processing, you might want to
  305. **    limit how many you process each time this routine is called.
  306. */
  307.  
  308. void    ProcessServerEvents(void)
  309. {
  310.     SERecQElemPtr    theSERecQElemPtr;
  311.     
  312.     while ( gExtendedSEQEntry.usedQ.qHead != NULL )
  313.     {
  314.         /* Get the server event record out of the usedQ */
  315.         theSERecQElemPtr = (SERecQElemPtr)gExtendedSEQEntry.usedQ.qHead;
  316.         if ( Dequeue((QElemPtr)theSERecQElemPtr, &gExtendedSEQEntry.usedQ) == noErr )
  317.         {
  318.             /* Do something useful with the server event record: */
  319.             /*     theSERecQElemPtr->theSERec */
  320.             
  321.             /* • add your code here • */
  322.             
  323.             /* We're done with the server event record, so put it back */
  324.             /* in the freeQ */
  325.             Enqueue((QElemPtr)theSERecQElemPtr, &gExtendedSEQEntry.freeQ);
  326.         }
  327.     }
  328. }
  329.  
  330. /*****************************************************************************/
  331.  
  332. /*
  333. **    Your application calls InstallServerEventHandler to install the server
  334. **    event handler. Change the InitSEQEntry function where indicated to tell
  335. **    the server event handler mechanism what server events you're interested
  336. **    in to begin with.
  337. */
  338.  
  339. OSErr    InstallServerEventHandler(void)
  340. {
  341.     OSErr    result;
  342.     
  343.     /* Initialize queues and get server event record buffer */
  344.     if ( InitSEQEntry() == true )
  345.     {
  346.         /* Set the server event flags in */
  347.         /* gExtendedSEQEntry.theSEQEntry */
  348.         SetSEFlags();
  349.  
  350.         /* Install the server event handler */
  351.         result = MySCInstallServerEventProc(&gExtendedSEQEntry.theSEQEntry);
  352.  
  353.         if ( result != noErr )    /* SE handler not installed? */
  354.         {
  355.             /* Then get rid of memory */
  356.             DisposPtr((Ptr)gExtendedSEQEntry.seRecArrayPtr);
  357.         }
  358.     }
  359.     else
  360.     {
  361.         /* Return a memory error */
  362.         result = memFullErr;
  363.     }
  364.     
  365.     return ( result );
  366. }
  367.  
  368. /*****************************************************************************/
  369.  
  370. /*
  371. **    Your application calls RemoveServerEventHandler to remove the server
  372. **    event handler and dispose of the memory allocated by InitSEQEntry (which
  373. **    is called by InstallServerEventHandler).
  374. */
  375.  
  376. OSErr    RemoveServerEventHandler(void)
  377. {
  378.     OSErr    result;
  379.     
  380.     /* Remove the server event handler */
  381.     result = MySCRemoveServerEventProc(&gExtendedSEQEntry.theSEQEntry);
  382.  
  383.     /* Get rid of memory used for the server event records */
  384.     if ( gExtendedSEQEntry.seRecArrayPtr != NULL )
  385.     {
  386.         DisposPtr((Ptr)gExtendedSEQEntry.seRecArrayPtr);
  387.     }
  388.     
  389.     return ( result );
  390. }
  391.  
  392. /*****************************************************************************/
  393.